﻿if (typeof jQuery === 'undefined') {
    throw new Error('jquery.popup JavaScript requires jQuery');
}

if (typeof Plugin === 'undefined') {
    throw new Error('jquery.popup JavaScript requires Plugin');
}


(function ($) {
    'use strict';

    var PopupWindow = function (el, options) {
        this.$el = $(el);
        this.namespace = _config_.popupWindow.namespace;
        this.defaults = _config_.popupWindow.defaults;
        this.methods = _config_.popupWindow.methods;
        this.events = _config_.popupWindow.events;

        this.initials = $.com.getDataBindFromElement(this.$el);
        this.originals = $.extend(true, {}, this.defaults, this.initials);
        this.originals.isGrid = this.$el.find(_config_.selector.grid).hasValue();
        this.options = $.extend(true, {}, this.originals, options);
        this.options.serial = $.com.getSerial(16);

        if ($.com.hasValue(this.originals.related)) {
            this.$related = $(this.originals.related);
        }

        //处理id
        this.getNamedPrefix('type');
        this.init();
    };

    PopupWindow.prototype = new Plugin();

    PopupWindow.prototype.init = function () {
        this.options = $.extend(true, {}, _config_.popupWindow.initials, this.calculateSize(), this.options);

        this.initPopup();
        this.initEvent();
    };

    PopupWindow.prototype.initPopup = function () {
        this.execute(this.options.loading);

        //kendo ui 方式
        this.options.close = (event) => this.onClose(event);

        this.$popup = this.$el.kendoWindow(this.options);
        this.popup = this.$el.data(this.options.role);

        this.$content = this.$el.find('.popup-content').first();
        if ($.com.isJqueryObject(this.$content)) {
            this.$forms = this.$el.find(this.options.form || _config_.selector.form);
            this.$form = this.$forms.first();
            this.$forms.needInitial().form();

            this.$grids = this.$el.find(this.options.grid || _config_.selector.grid);
            this.$grid = this.$grids.first();
            this.$grids.needInitial().grid();

            this.$body = this.$content.find('.popup-body').first();
            this.$footer = this.$content.find('.popup-footer').first();
            this.$buttons = this.$footer.find(_config_.selector.button);

            //var $buttons = this.$buttons.needInitial().button();
            //this.$selection = this.$el.find(this.options.selection || '.selection').first();
            //if ($.com.isJqueryObject(this.$selection) && (!$.com.hasValue(this.$selection.data(_config_.form.namespace)))) {
            //    this.$selection.addClass('row').css('padding', '0 10px');
            //    this.$selection.form();
            //    this.$selection.find('div.bootstrap-tagsinput').addClass('col-md-12').width('100%');
            //}

            //var $editors = this.$content.find('[data-role="kendoEditor"]');
            //if ($.com.isJqueryObject($editors)) {
            //    $editors.each((index, item) => {
            //        var $editor = $(item).parent().find('iframe').contents().find('body');
            //        if ($editor) {
            //            debugger;
            //            $editor.attr('autocorrect', 'off').attr('contenteditable', true);
            //        }
            //    });
            //}
        }

        this.$el.attr(_config_.attribute.initial, true);
        this.execute(this.options.loaded);
    };

    PopupWindow.prototype.initEvent = function () {
        var that = this;

        this.$el.off('open.' + this.namespace).on('open.' + this.namespace, function (event, options) {
            that.onOpen(event, options);
            event.stopPropagation();
        });

        if ($.com.isJqueryObject(this.$buttons)) {
            this.authorizeButton();

            this.$el.off('ok.' + this.namespace).on('ok.' + this.namespace, function (event) {
                that.onOk(event);
                event.stopPropagation();
            });

            this.$buttons.filter(_config_.selector.okButton).click(function (event) {
                that.$el.trigger('ok');
                event.stopPropagation();
            });

            this.$el.off('close.' + this.namespace).on('close.' + this.namespace, function (event) {
                that.popup.close();
                event.stopPropagation();
            });

            this.$buttons.filter(_config_.selector.closeButton).click(function (event) {
                that.$el.trigger('close');
                event.stopPropagation();
            });

            this.$el.off('query.' + this.namespace).on('query.' + this.namespace, function (event) {
                //that.onQuery(event, 'query');
                event.stopPropagation();
            });

            let $buttons = this.$buttons.filter(_config_.selector.closeOnSuccess);
            if ($.com.isJqueryObject($buttons) && $buttons.isButton()) {
                $buttons.each((index, element) => {
                    let button = $(element).data(_config_.button.namespace);
                    if ($.com.hasValue(button)) {
                        const success = button.options.success;
                        button.options.success = (el, data, event) => {
                            if (typeof success === 'function') {
                                success(el, data, event);
                            }

                            this.popup.close();

                            //事件为 add, update, delete, 执行完毕之后执行关联 form 的 query 事件刷新表格
                            if ($.com.isJqueryObject(this.$related) && this.$related.isForm()) {
                                let $button = this.$related.find(_config_.selector.queryButton);
                                if ($.com.isJqueryObject($button)) {
                                    $button.click();
                                }
                            }
                        };;
                    }
                });
            }
        }
    };

    // popup 中存在 grid 的情况下单选和多选的处理
    PopupWindow.prototype.select = function (data, dblclick) {
        if ($.com.hasValue(data)) {
            this.options.data = data;
            if ($.com.isArray(data) && $.com.isJqueryObject(this.$selection)) {
                //多选模式 $selection赋值
                var $field = this.$selection.find('[role="tagsinput"]:first');
                if ($.com.hasValue($field)) {
                    for (var i = 0; i < data.length; i++) {
                        $field.tagsinput('add', data[i]);
                    }

                    this.options.data = $field.tagsinput('items');
                }
            } else {
                if (dblclick) {
                    //单选且双击, 则返回
                    this.onOk();
                }
            }
        } else {
            return this.options.data;
        }
    };

    // destroy
    PopupWindow.prototype.destroy = function () {
        this.$el.removeData(this.namespace);
        this.$el.remove();
    };

    PopupWindow.prototype.onOpen = function (event, options) {
        options = options || {};
        this.options.multiple = options.multiple || this.originals.multiple || this.options.multiple;
        this.options = $.extend(true, {}, this.calculateSize(), this.originals, options);

        //打开前, 现在前置事件只需返回 false 就可以阻止事件继续执行
        var ret = this.execute(this.options.opening, event);
        if ($.com.hasValue(ret) && ret === false) {
            return;
        }

        //重新计算 field 和 formData 的值
        $.com.getFromPopupParameter(this.options);

        this.popup.setOptions(this.options);
        this.popup.center().open();

        if ($.com.isJqueryObject(this.$content) && $.com.isJqueryObject(this.$footer)) {
            this.$content.height(this.$popup.height() - this.$footer.height() - 20);
            if ($.com.isJqueryObject(this.$body)) {
                this.$body.height(this.$content.height());
            }
        }
        //$content.removeClass('multiple');
        //if (this.options.isGrid) {
        //    //if (this.options.isMultiple) {
        //    //    this.$selection.show();
        //    //    $content.addClass('multiple');
        //    //} else {
        //    //    this.$selection.hide();
        //    //}

        //    //TODO TBC 难度太高, 暂不实现
        //    //if ($.com.isJqueryObject(this.$grid) && $.com.isArray(this.options.popupParameter)) {
        //    //    //处理预选中, 即当前传进来的数据出现在 grid 数据列表中则选中(排除出现在其他页的情况)
        //    //    let grid = this.$grid.data(_config_.grid.namespace);
        //    //    if ($.com.hasValue(grid) && $.com.hasValue(grid).role) {
        //    //        let gridData = grid.role.dataSource.data();
        //    //        if ($.com.isArrayLike(gridData)) {

        //    //        }
        //    //    }
        //    //}

        //} else {
        //    $content.addClass('multiple');
        //}

        //包含的 form 组件赋值
        if ($.com.isJqueryObject(this.$form)) {
            var form = this.$form.data(_config_.form.namespace);
            form.reset();

            if ($.com.hasValue(this.options.editable)) {
                form.options.editable = this.options.editable;
            }

            if ($.com.hasValue(this.options.detailable)) {
                form.options.detailable = this.options.detailable;
            }
            //if ($.com.hasValue(this.options.filterable)) {
            //    form.options.filterable = this.options.filterable;
            //}

            form.refresh(this.options.formData, true);
            if (form.options.filterable) {
                //打开后取消作为查询区的 form 中的验证
                form.validate(false);
            }

            //if (form.options.editable) {
            //    form.$buttons.filter(`${_config_.selector.postButton},${_config_.selector.deleteButton}`).button('display', false);
            //    form.$buttons.filter(_config_.selector.putButton).button('display', true);
            //} else {
            //    let $postButton = form.$buttons.filter(_config_.selector.postButton);
            //    if ($postButton.hasValue()) {
            //        form.$buttons.filter(`${_config_.selector.putButton},${_config_.selector.deleteButton},${_config_.selector.passedButton}`).button('display', false);
            //        form.$buttons.filter(_config_.selector.postButton).button('display', true);
            //    } else {
            //        form.$buttons.filter(`${_config_.selector.putButton},${_config_.selector.deleteButton}`).button('display', true);
            //    }
            //}
        }

        //重置选择区域
        this.reselection();

        //包含的 grid 组件执行查询
        if ($.com.isJqueryObject(this.$grids)) {
            this.$grids.grid('query');
        }

        //如果弹出框是一个打印预览
        if (this.options.type === 'PrintTable' && $.com.isJqueryObject(this.$buttons)) {
            var $printButton = this.$buttons.filter('[data-button="print"]');
            if ($.com.isJqueryObject($printButton)) {
                var button = $printButton.data(_config_.button.namespace);
                if ($.com.hasValue(button)) {
                    button.printTable = new PrintTable(this);
                }
            }
        }

        //成功打开后
        this.execute(this.options.opened, event);
    };

    // popupWindow on search event
    PopupWindow.prototype.onOk = function (event) {
        //关闭前 TODO
        //if (this.options.isMultiple) {
        //    this.options.data = this.$selection.find('[role="tagsinput"]:first').tagsinput('items') || [];
        //}

        //现在前置事件只需返回 false 就可以阻止事件继续执行
        var ret = this.execute(this.options.closing, event);
        if ($.com.hasValue(ret) && ret === false) {
            return;
        }

        //var data = $.extend(true, [], this.options.data);
        var data = $.com.cleanData(this.options.data);

        ret = this.execute(this.options.confirming, event, data);
        if ($.com.hasValue(ret) && ret === false) {
            return;
        }

        // TBC ***** 此处待验证, 是否可所有情况均按对象方式处理
        if ($.com.hasValue(this.options.openerProperty)) {
            this.fillOpenerProperty(data);
        } else if (this.options.fillFormData) {
            this.fillFormData(data);
        } else {
            if ($.com.isArray(this.options.parameter)) {
                this.fillOpener(data);
            }
        }

        this.popup.close();

        //关闭后
        this.execute(this.options.confirmed, event);
        this.execute(this.options.closed, event);
    };

    // popupWindow on search event
    PopupWindow.prototype.onClose = function (event) {
        //关闭前
        this.execute(this.options.closing, event);

        //this.popup.close();

        //关闭后
        this.execute(this.options.closed, event);
    };

    PopupWindow.prototype.calculateSize = function () {
        this.options.size = this.options.size || 'default';
        //if (this.options.isGrid) {
        //    this.options.isMultiple = typeof this.options.multiple === 'string' && this.options.multiple.startsWith('multiple');
        //    if (this.options.isMultiple) {
        //        this.options.size = 'multiple';
        //    } else {
        //        this.options.size = 'single';
        //    }
        //}

        var size = _config_.popupWindow.size[this.options.size];
        if (!$.com.hasValue(size)) {
            size = _config_.popupWindow.size.default;
        }

        return size;
    };

    PopupWindow.prototype.reselection = function () {
        if ($.com.isJqueryObject(this.$selection)) {
            //this.$selection.css('display', 'grid');
            var $field = this.$selection.find('[role="tagsinput"]:first');
            if ($.com.isJqueryObject($field)) {
                var data = $.extend(true, [], this.options.data);
                $field.tagsinput('removeAll');
                this.select(data);
            }
        }

        this.options.data = [];
    };

    /**
     * 使用 inout 填充 opener 指定字段
     */
    PopupWindow.prototype.fillOpener = function (data) {
        var $opener = $(this.options.opener);
        var outs = this.options.parameter.where(function (x) { return x.transfer.includes('out'); });
        if ($.com.isJqueryObject($opener) && $.com.isArray(outs)) {
            data = data || [];
            if (!$.com.isArray(data)) {
                data = [data];
            }

            for (var i = 0; i < outs.length; i++) {
                var x = outs[i];
                if ($.com.hasValue(x.target) && $.com.hasValue(x.source)) {
                    var targets = data.select(x.target);
                    if ($.com.isArray(targets)) {
                        x.value = targets.length === 1 ? targets[0] : targets.join(', ');
                    } else {
                        x.value = null;
                    }

                    var $el = $opener.find('[' + _config_.attribute.field + '="' + x.source + '"]');
                    if ($.com.isJqueryObject($el)) {
                        var field = $el.data(_config_.field.namespace);
                        if ($.com.hasValue(field)) {
                            field.refresh(x.value, true);
                            if ($el.is('span,label,a')) {
                                field.writeBack();
                            } else {
                                $el.change();
                            }
                        } else {
                            if ($el.is('span,label,a')) {
                                $el.html(x.value);
                            } else {
                                $el.val(x.value).change();
                            }
                        }
                    }
                }
            }
        }
    };

    /**
     * 使用同名匹配字段直接填充整个 form data
     * 条件, opener 是一个 form, 弹出框为单选模式
     */
    PopupWindow.prototype.fillFormData = function (data) {
        var $opener = $(this.options.opener);
        if ($.com.isJqueryObject($opener) && $.com.hasValue(data) && !$.com.isArray(data)) {
            let form = $opener.data(_config_.form.namespace);
            if ($.com.hasValue(form)) {
                form.fillFormData(data);
            }
        }
    }

    /**
     * 按对象处理填充 form data 的字段
     */
    PopupWindow.prototype.fillOpenerProperty = function (data) {
        var d = {};
        var formData = $.com.getFormData(this.options.opener);
        if ($.com.hasValue(formData)) {
            if ($.com.isArray(data)) {
                formData[this.options.openerProperty] = data[0];
            } else {
                delete formData[this.options.openerProperty];
            }

            var prefix = this.options.opener.attr(_config_.default.parameterPrefix) || _config_.default.parameterPrefixValue;
            for (var key in this.options.inout) {
                var value = this.options.inout[key];
                if (typeof value === 'string' && !value.startsWith(prefix)) {
                    if ($.com.isArray(data)) {
                        d[value] = data.select(key).join(', ');
                    } else {
                        delete formData[value];
                    }
                }
            }
        }

        formData = $.extend(formData, d);
        this.options.opener.form('refresh', formData, true);
    };

    // plug-in
    $.fn.popupWindow = function (options) {
        var args = Array.prototype.slice.call(arguments, 1);
        var value = undefined;
        this.each(function () {
            var $this = $(this);
            var data = $this.data(_config_.popupWindow.namespace);
            // initial if nover
            if ($.com.isNullOrEmpty(data)) {
                data = new PopupWindow(this, typeof options === 'object' && options);
                $this.data(_config_.popupWindow.namespace, data);
            }

            if (typeof options === 'string') {
                //if options is not a method
                if ($.inArray(options, data.methods) < 0) {
                    throw 'Unknown method: ' + options;
                }

                //if options is a plugin method, to execute
                value = data[options].apply(data, args);
            }
        });

        return typeof value === 'undefined' ? this : value;
    };
})(jQuery);

(function ($) {
    'use strict';

    var Popup = function (el, options) {
        this.$el = $(el);
        this.namespace = _config_.popup.namespace;
        this.defaults = _config_.popup.defaults;
        this.methods = _config_.popup.methods;
        this.events = _config_.popup.events;
        this.initials = $.com.getDataBindFromElement(this.$el);
        this.originals = $.extend(true, {}, this.defaults, this.initials);
        this.originals.serial = $.com.getSerial(16);
        this.options = $.extend(true, {}, this.originals, options);
        this.init();
    };

    Popup.prototype = new Plugin();

    Popup.prototype.init = function () {
        this.$popup = $(this.options.popup);
        if (!$.com.isJqueryObject(this.$popup)) {
            this.$popup = $('[data-type="' + this.options.popup + '"]');
        }

        this.$form = this.$el.parents(_config_.selector.form).first();
        if (!this.$el.isBelongToForm(this.$form)) {
            this.$form = $(_config_.selector.default);
        }

        let button = this.$el.data(_config_.button.namespace);
        if ($.com.hasValue(button)) {
            let withFormData = $.com.getValue(button, 'options.withFormData');
            if ($.com.hasValue(withFormData)) {
                this.options.withFormData = withFormData;
            }
        }

        this.initEvent();
    };

    Popup.prototype.initEvent = function () {
        this.$el.off('open.' + this.namespace).on('open.' + this.namespace, (event, options) => this.onOpen(event, options));

        if ($.com.hasValue(this.options.field) && this.$el.is('[data-icon]')) {
            if (!$.com.isJqueryObject(this.$fieldset)) {
                this.$fieldset = this.$el.field('getValue', '$fieldset');
            }

            if ($.com.isJqueryObject(this.$fieldset)) {
                var $icon = this.$fieldset.find('.field-group-addon');
                $icon.css('cursor', 'pointer').off('click.' + this.namespace).on('click.' + this.namespace, event => this.trigger(event, 'open'));
            }
        } else {
            this.$el.off('click.' + this.namespace).on('click.' + this.namespace, (event, options) => this.onOpen(event, options));
        }
    };

    /*
    *   popupParameter 属性, 有以下属性
    *   opener: undefined, 打开者 / 接收者, 默认取当前组件所在 form;
    *   parameter: 传入传出参数列表, 默认情况下将使用当前字段自动构造
    *   inout: [], 这个参数是原来 parameter 参数的简写形式, 由左侧 in 属性名 = 右侧 out 属性名/值来构成; 如果无此参数, 则默认用当前元素构造出来
    *   formData: 指示使用当前 form data 作为传入参数
    *   fillFormData: 指示是否填充整个表单数据
    */
    Popup.prototype.onOpen = function () {
        //弹出框可触发弹出事件的前提是: 1. popup 属性指定的元素存在, 2. enable 属性为 true 且 editable 为 false(为 true 时, 不可触发事件)
        if ($.com.isJqueryObject(this.$popup) && this.isTrue('enable') && !this.isTrue('editable')) {

            this.options.popupParameter = $.extend(true, {}, this.originals.popupParameter, {
                opening: this.options.opening,
                opened: this.options.opened,
                confirming: this.options.confirming,
                confirmed: this.options.confirmed,
                closing: this.options.closing,
                closed: this.options.closed,
                withFormData: this.options.withFormData,
                fillFormData: this.options.fillFormData
            });

            //1. 获取 opener
            var $opener = $(this.options.opener || this.options.popupParameter.opener || _config_.selector.default);
            this.options.popupParameter.opener = $.com.isJqueryObject($opener) ? $opener : this.$form;
            if (!$.com.isJqueryObject(this.options.popupParameter.opener)) {
                this.options.popupParameter.opener = $.com.isJqueryObject(this.$el.children(_config_.selector.field)) ? this.$el : this.$el.parent();
            }

            //if (this.options.popupParameter.opener.isForm() && this.$el.isButton() && this.options.button === 'printView') {
            //    this.options.popupParameter.opener = this.$el;
            //}

            //2. 获取 popupParameter
            if (!$.com.isArray(this.options.popupParameter.parameter) && !$.com.hasValue(this.options.popupParameter.inout)) {
                this.options.popupParameter.parameter = [{
                    transfer: this.options.transfer || 'out',
                    source: this.options.source || this.options.field || 'name',
                    target: this.options.target || this.options.field || 'name'
                }];
            }

            let openerForm = {};
            if (this.$form.isForm()) {
                openerForm = this.$form.data(_config_.form.namespace);
            }

            //3. 计算传入参数的 formData, 此 formData 为内部弹出框的 form 区域数据, 并非启动器的 formData
            if (this.options.popupParameter.opener.equal(this.$form) && this.options.withFormData) {
                this.options.popupParameter.formData = openerForm.options.data;
            } else {
                this.options.popupParameter.formData = {};
                for (var index = 0; index < this.options.popupParameter.parameter.length; index++) {
                    let params = this.options.popupParameter.parameter[index];
                    let value = $.com.getValue(openerForm, "options.data." + params.source);
                    if ($.com.hasValue(value)) {
                        this.options.popupParameter.formData[params.source] = value;
                    }
                }
            }

            //编辑按钮打开的弹出框中的 form 会被标记为编辑模式
            this.options.popupParameter.editable = this.$el.is(_config_.selector.editButton);
            $.com.getPopupParameterValue(this.options.popupParameter);

            //传入参数为: popupParameter:{opener, parameter}, 其余参数现在放在 opening 之后获取
            this.$popup.filter('[id]').first().trigger('open', [this.options.popupParameter]);

            //父级弹出框存在且打开的弹出框为编辑模式则关闭, 针对先打开了 详情弹出框 在打开 编辑弹出框 的情况
            if (this.options.popupParameter.editable) {
                let $popup = this.$el.closest(_config_.selector.popupWindow);
                if ($.com.isJqueryObject($popup)) {
                    $popup.trigger('close');
                }
            }
        }
    };

    // plug-in
    $.fn.popup = function (options) {
        var args = Array.prototype.slice.call(arguments, 1);
        var value = undefined;
        this.each(function () {
            var $this = $(this);
            var data = $this.data(_config_.popup.namespace);
            // initial if nover
            if ($.com.isNullOrEmpty(data)) {
                data = new Popup(this, typeof options === 'object' && options);
                $this.data(_config_.popup.namespace, data);
            }

            if (typeof options === 'string') {
                //if options is not a method
                if ($.inArray(options, data.methods) < 0) {
                    throw 'Unknown method: ' + options;
                }

                //if options is a plugin method, to execute
                value = data[options].apply(data, args);
            }
        });

        return typeof value === 'undefined' ? this : value;
    };
})(jQuery);